﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Security.Cryptography;
namespace TuiXin
{


    namespace DEMO
    {
        namespace MSG
        {
            #region enum
            public enum COMMAND_ID : uint
            {
                BIND = 0x00000001,
                BIND_RESP = 0x80000001,

                TERMINATE = 0x00000002,  // 终止连接
                TERMINATE_RESP = 0x80000002,  // 终止连接应答

                ACTIVE_TEST = 0x00000003, //激活测试
                ACTIVE_TEST_RESP = 0x80000003,

                CLIENT_MSG = 0x000000010,
                CLIENT_MSG_RESP = 0x80000010,

                SERVER_MSG = 0x00000020,
                SERVER_MSG_RESP = 0x80000020
            }

            public enum EVENT_TYPE
            {
                OnBind = 0,
                OnBindResp = 1,
                OnUnbind = 2,
                OnUnbindResp = 3,
                OnTest = 4,
                OnTestResp = 5,
                OnClosed = 6,
                OnClientMsg = 7,
                OnClientMsgResp = 8,
                OnServerMsg = 9,
                OnServerMsgResp = 10

            }

            #endregion


            public class MSG_HEADER
            {
                private byte[] Header = new byte[MSG.MSG_HEADER.HeaderLength];


                public MSG_HEADER(COMMAND_ID Command_ID) //发送前
                {
                    BIConvert.Int2Bytes((uint)Command_ID).CopyTo(Header, 4);
                }

                public MSG_HEADER(byte[] bs) //根据受到的字节进行构造 字节序列
                {
                    for (int i = 0; i < MSG.MSG_HEADER.HeaderLength; i++)
                    {
                        Header[i] = bs[i];
                    }
                }
                public MSG_HEADER(byte[] bs, int baseIndex) //根据受到的字节进行构造 字节序列
                {
                    for (int i = 0; i < MSG.MSG_HEADER.HeaderLength; i++)
                    {
                        Header[i] = bs[baseIndex + i];
                    }
                }
                public MSG_HEADER()
                {
                }


                public uint MSG_Length  //获取此消息头代表的消息的整个长度
                {
                    get
                    {
                        return (BIConvert.Bytes2UInt(Header, 0));
                    }
                    set
                    {
                        byte[] t = BIConvert.Int2Bytes(value);
                        for (int i = 0; i < 4; i++)
                        {
                            Header[i] = t[i];
                        }
                    }
                }

                public uint Command_ID
                {
                    get
                    {
                        return (BIConvert.Bytes2UInt(Header, 4));
                    }
                    set
                    {
                        byte[] t = BIConvert.Int2Bytes(value);
                        for (int i = 0; i < 4; i++)
                        {
                            Header[i + 4] = t[i];
                        }
                    }
                }

                public uint Seq_ID
                {
                    get
                    {
                        return (BIConvert.Bytes2UInt(Header, 8));
                    }
                    set
                    {
                        byte[] t = BIConvert.Int2Bytes(value);
                        for (int i = 0; i < 4; i++)
                        {
                            Header[i + 4 + 4] = t[i];
                        }
                    }
                }

                public byte[] GetBytes()
                {
                    return (Header); //将字段转化为字节
                }

                public void SetBytes(byte[] bs)
                {
                    for (int i = 0; i < MSG.MSG_HEADER.HeaderLength; i++)
                    {
                        Header[i] = bs[i];
                    }
                }

                public static int HeaderLength
                {
                    get
                    {
                        return (4 + 4 + 4);
                    }
                }
            }

            #region BIND
            public class BIND
            {
                MSG_HEADER header;

                int _LoginType = 0;
                string _UserName = "000000";
                public string UserName
                {
                    get
                    {
                        return (this._Password);
                    }
                    set
                    {
                        this._UserName = value;
                    }
                }


                string _Password = "00000000";
                public string Password
                {
                    get
                    {
                        return (this._Password);
                    }
                    set
                    {
                        _Password = value;
                    }
                }

                string _Reserve = "";


                public BIND(uint sequence)
                {
                    header = new MSG.MSG_HEADER(MSG.COMMAND_ID.BIND);
                    header.Seq_ID = sequence;
                    header.MSG_Length = (uint)(this.BodyLength + MSG.MSG_HEADER.HeaderLength);
                }
                public BIND(byte[] bs)
                {
                    int index = 12;
                    index = index + 1;

                    this._UserName = Encoding.ASCII.GetString(bs, index, 16);
                    index = index + 16;

                    this._Password = Encoding.ASCII.GetString(bs, index, 16);
                    index = index + 16;

                    CheckLogin();
                }
                public int BindResult = 0;
                void CheckLogin()
                {

                    BindResult = 0;
                }
                public int BodyLength
                {
                    get
                    {
                        return (1 + 16 + 16 + 8);
                    }
                }


                public byte[] GetBytes()   //返回当前对象的字节数组印象
                {
                    byte[] reVal = new Byte[MSG.MSG_HEADER.HeaderLength + this.BodyLength];
                    header.GetBytes().CopyTo(reVal, 0);       //消息头
                    int index = 12;
                    reVal[index++] = (byte)this._LoginType;
                    byte[] username = Encoding.ASCII.GetBytes(this._UserName);
                    username.CopyTo(reVal, index);
                    index += 16;
                    byte[] pwd = Encoding.ASCII.GetBytes(this._Password);
                    pwd.CopyTo(reVal, index);
                    index += 16;
                    byte[] reserve = Encoding.ASCII.GetBytes(this._Reserve);
                    reserve.CopyTo(reVal, index);
                    index += 8; //reserve
                    return (reVal);
                }
            }
            public class BIND_RESP
            {
                MSG_HEADER header;

                public BIND_RESP(byte[] bs)
                {
                    this._Result = (int)bs[12 + 1];
                }


                int _Result = 0;
                public int Result
                {
                    set
                    {
                        this._Result = value;
                    }
                    get
                    {
                        return (this._Result);
                    }
                }

                public BIND_RESP(uint seqID)
                {
                    header = new MSG_HEADER(COMMAND_ID.BIND_RESP);
                    header.Seq_ID = seqID;

                    header.MSG_Length = (uint)MSG_HEADER.HeaderLength + 1 + 8;
                }

                public byte[] GetBytes()   //返回当前对象的字节数组印象
                {
                    byte[] reVal = new Byte[12 + 1 + 8];
                    header.GetBytes().CopyTo(reVal, 0);       //消息头
                    int index = 12;
                    reVal[index++] = (byte)this._Result;
                    index += 8; //reserve
                    return (reVal);
                }
            }
            #endregion

            #region CLIENT_MSG
            public class CLIENT_MSG
            {
                MSG_HEADER header;

                public ClientMsg clientMsg = new ClientMsg();

                public CLIENT_MSG(uint seq)
                {
                    header = new MSG_HEADER(COMMAND_ID.CLIENT_MSG);
                    header.Seq_ID = seq;

                }

                public CLIENT_MSG(byte[] bs)
                {
                    int index = 12;
                    index = index + 4;
                    clientMsg.Name = Encoding.Default.GetString(bs, index, GetRealLen(bs, index));
                    index = index + 50;
                    clientMsg.Class = Encoding.Default.GetString(bs, index, GetRealLen(bs, index));
                    index = index + 30;
                    clientMsg.Quantity = BIConvert.Bytes2UInt(bs, index);
                    index = index + 4;
                    clientMsg.Location = Encoding.Default.GetString(bs, index, GetRealLen(bs, index));

                }

                public byte[] GetBytes() //返回字节数印象
                {
                    byte[] submitData = new byte[800];
                    int index = MSG.MSG_HEADER.HeaderLength;
                    {
                        #region 进入填充包的过程
                        BIConvert.Int2Bytes(clientMsg.ID).CopyTo(submitData, index);
                        index = index + 4;

                        byte[] msg = Encoding.Default.GetBytes(clientMsg.Name);
                        msg.CopyTo(submitData, index);
                        index = index + 50;

                        msg = Encoding.Default.GetBytes(clientMsg.Class);
                        msg.CopyTo(submitData, index);
                        index = index + 30;


                        BIConvert.Int2Bytes(clientMsg.Quantity).CopyTo(submitData, index);
                        index = index + 4;

                        msg = Encoding.Default.GetBytes(clientMsg.Location);
                        msg.CopyTo(submitData, index);
                        index = index + 30;

                        index = index + 8;
                        #endregion
                    }

                    header.MSG_Length = (uint)index;
                    byte[] reVal = new byte[index];
                    header.GetBytes().CopyTo(reVal, 0);
                    for (int i = MSG_HEADER.HeaderLength; i < reVal.Length; i++)
                    {
                        reVal[i] = submitData[i];
                    }

                    return (reVal);
                }

                private int GetRealLen(byte[] bts, int index)
                {
                    int i = index;
                    for (; i < bts.Length; i++)
                    {
                        if (bts[i] == 0)
                        {
                            break;
                        }
                    }
                    return i - index;
                }
            }
            public class CLIENT_MSG_RESP
            {

                MSG_HEADER header;
                int _Result = 0;
                public int Result
                {
                    set
                    {
                        this._Result = value;
                    }
                    get
                    {
                        return (this._Result);
                    }
                }
                public CLIENT_MSG_RESP(byte[] bs)
                {
                    this._Result = (int)bs[12 + 1];
                }

                public CLIENT_MSG_RESP(uint seq)
                {
                    header = new MSG_HEADER(COMMAND_ID.CLIENT_MSG_RESP);
                    header.Seq_ID = seq;
                    header.MSG_Length = (uint)MSG_HEADER.HeaderLength + 1 + 8;
                }
                public byte[] GetBytes()
                {
                    byte[] reVal = new byte[MSG_HEADER.HeaderLength + 1 + 8];
                    int index = 0;
                    header.GetBytes().CopyTo(reVal, index);
                    index += 12;
                    reVal[index++] = (byte)this._Result;
                    index += 8; //reserve
                    return (reVal);
                }
            }
            #endregion

            #region SERVER_MSG
            public class SERVER_MSG : AtomBase
            {

                MSG_HEADER header;

                public SERVER_MSG(byte[] bs)
                {


                }
            }

            public class SERVER_MSG_RESP
            {

                MSG_HEADER header;
                int _result = 0;

                public SERVER_MSG_RESP(uint sequence)
                {
                    header = new MSG_HEADER(COMMAND_ID.SERVER_MSG_RESP);
                    header.Seq_ID = sequence;
                    header.MSG_Length = (uint)MSG_HEADER.HeaderLength + 10 + 4;

                }

                public int Result
                {
                    set
                    {
                        this._result = value;
                    }
                }

                public byte[] GetBytes()
                {
                    byte[] reVal = new byte[MSG.MSG_HEADER.HeaderLength + 10 + 4];

                    return (reVal);
                }

            }
            #endregion

            #region Terminate and test
            public class MSG_TEST
            {

                MSG_HEADER header;
                public MSG_TEST(uint sequence)
                {
                    header = new MSG.MSG_HEADER(MSG.COMMAND_ID.ACTIVE_TEST);
                    header.MSG_Length = (uint)MSG.MSG_HEADER.HeaderLength;
                    header.Seq_ID = sequence;
                }

                public MSG_TEST(byte[] bs)
                {
                    header = new MSG.MSG_HEADER(bs);
                }

                public byte[] GetBytes()
                {
                    return (header.GetBytes());
                }

                public uint Sequence
                {
                    get
                    {
                        return (header.Seq_ID);
                    }
                }
            }

            public class MSG_TEST_RESP
            {
                MSG_HEADER header;

                public MSG_TEST_RESP(uint sequence)
                {
                    header = new MSG.MSG_HEADER(MSG.COMMAND_ID.ACTIVE_TEST_RESP);
                    header.MSG_Length = (uint)MSG.MSG_HEADER.HeaderLength;
                    header.Seq_ID = sequence;
                }

                public MSG_TEST_RESP(byte[] bs)
                {
                    header = new MSG.MSG_HEADER(bs);
                }

                public uint Sequence
                {
                    get
                    {
                        return (header.Seq_ID);
                    }
                }

                public byte[] GetBytes()
                {
                    byte[] reVal = new byte[MSG.MSG_HEADER.HeaderLength];
                    header.GetBytes().CopyTo(reVal, 0);
                    return (reVal);
                }

            }

            public class MSG_TERMINATE
            {
                MSG_HEADER header;
                public MSG_TERMINATE(uint sequence)
                {
                    header = new MSG.MSG_HEADER(MSG.COMMAND_ID.TERMINATE);
                    header.MSG_Length = (uint)MSG.MSG_HEADER.HeaderLength;
                    header.Seq_ID = sequence;
                }
                public MSG_TERMINATE(byte[] bs)
                {
                    header = new MSG.MSG_HEADER(bs);
                }

                public byte[] GetBytes()
                {
                    return (header.GetBytes());
                }

                public uint Sequence
                {
                    get
                    {
                        return (header.Seq_ID);
                    }
                }
            }

            public class MSG_TERMINATE_RESP
            {
                MSG_HEADER header;
                public MSG_TERMINATE_RESP(byte[] bs)
                {
                    header = new MSG_HEADER(bs);
                }
                public MSG_TERMINATE_RESP(uint sequence)
                {

                    header = new MSG_HEADER(COMMAND_ID.TERMINATE_RESP);
                    header.MSG_Length = (uint)MSG_HEADER.HeaderLength;
                    header.Seq_ID = sequence;

                }

                public byte[] GetBytes()
                {
                    return (header.GetBytes());
                }

                public uint Sequence
                {
                    get
                    {
                        return (header.Seq_ID);
                    }
                }
            }

            #endregion

            #region 字节 整形 转换类 网络格式转换为内存格式
            public class BIConvert  //字节 整形 转换类 网络格式转换为内存格式
            {
                public static byte[] Int2Bytes(uint i)  //转换整形数据网络次序的字节数组
                {
                    byte[] t = BitConverter.GetBytes(i);
                    byte b = t[0];
                    t[0] = t[3];
                    t[3] = b;
                    b = t[1];
                    t[1] = t[2];
                    t[2] = b;
                    return (t);
                }

                public static uint Bytes2UInt(byte[] bs, int startIndex) //返回字节数组代表的整数数字，4个数组
                {
                    byte[] t = new byte[4];
                    for (int i = 0; i < 4 && i < bs.Length - startIndex; i++)
                    {
                        t[i] = bs[startIndex + i];
                    }
                    byte b = t[0];
                    t[0] = t[3];
                    t[3] = b;
                    b = t[1];
                    t[1] = t[2];
                    t[2] = b;
                    return (BitConverter.ToUInt32(t, 0));
                }

                public static uint Bytes2UInt(byte[] bs)  //没有指定起始索引
                {
                    return (Bytes2UInt(bs, 0));
                }

                public static void DumpBytes(byte[] bs, string txt)
                {
                    try
                    {

                        System.IO.StreamWriter sw = new System.IO.StreamWriter(txt);
                        for (int i = 0; i < bs.Length; i++)
                        {
                            byte b = bs[i];
                            sw.Write(b.ToString("X").PadLeft(2, '0') + " ");
                        }
                        sw.WriteLine("-----------");
                        sw.WriteLine(DateTime.Now.ToLocalTime());
                        sw.Close();
                    }
                    catch
                    {
                    }
                }

                public static void DebugString(string bs, string txt)
                {
                    System.IO.StreamWriter sw = new System.IO.StreamWriter(txt);
                    sw.WriteLine(bs);
                    sw.WriteLine("-----" + DateTime.Now.ToLocalTime());
                    sw.Close();
                }
            }
            #endregion

            #region EventArgs
            //Only one DEMO event call back     
            public class DEMOEventArgs : EventArgs
            {
                public ClientMsg clientMsg = new ClientMsg();
                public ServerMsg serverMsg = new ServerMsg();

                public EVENT_TYPE Event_Type = new EVENT_TYPE();

                private int _SocketIndex;
                public int SocketIndex
                {
                    get
                    {
                        return (this._SocketIndex);
                    }
                    set
                    {
                        this._SocketIndex = value;
                    }
                }

                private string _Msg = "";
                public string Msg
                {
                    get
                    {
                        return (this._Msg);
                    }
                    set
                    {
                        this._Msg = value;
                    }
                }

                public DEMOEventArgs()
                {
                }

            }


            #endregion


            public class ClientMsg
            {
                public ClientMsg()
                {
                }
                #region 字段属性

                uint _ID = 0;
                public uint ID
                {
                    get
                    {
                        return (this._ID);
                    }
                    set
                    {
                        this._ID = value;
                    }
                }

                string _Name = "";
                public string Name
                {
                    get
                    {
                        return (this._Name);
                    }
                    set
                    {
                        this._Name = value.Trim();
                    }
                }

                string _Class = "";
                public string Class
                {
                    get
                    {
                        return (this._Class);
                    }
                    set
                    {
                        this._Class = value.Trim();
                    }
                }
                uint _Quantity = 0;
                public uint Quantity
                {
                    get
                    {
                        return (this._Quantity);
                    }
                    set
                    {
                        this._Quantity = value;
                    }
                }
                string _Location = "";
                public string Location
                {
                    get
                    {
                        return (this._Location);
                    }
                    set
                    {
                        this._Location = value.Trim();
                    }
                }

                #endregion
            }
            public class ServerMsg
            {
                public ServerMsg()
                {
                }
            }

        }
        public class CDEMO : AtomBase
        {
            #region   SeqNumber
            private uint lastSeq = uint.MaxValue;   //流水号，每一次重新启动都需要重新设定 lastSequence
            private uint getNextSequence()
            {
                lock (typeof(CDEMO))
                {
                    try
                    {
                        lastSeq--;
                    }
                    catch (OverflowException ofe)
                    {
                        lastSeq = uint.MaxValue;
                    }
                    return (lastSeq);
                }
            }

            #endregion



            public Socket socket;
            public CDEMO()
            {

            }
            private AddressFamily addressFamily;
            private SocketType socketType;
            private ProtocolType protocolType;
            public int SocketID;
            public CDEMO(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
            {
                socket = new Socket(addressFamily, socketType, protocolType);
                this.addressFamily = addressFamily;
                this.socketType = socketType;
                this.protocolType = protocolType;
            }
            private void TimeCall(object stat)
            {
                log.Msg("TimeCall", DateTime.Now.ToString());
                if (this.Connected)
                {
                    this.Send_COMMAND(DEMO.MSG.COMMAND_ID.ACTIVE_TEST);
                    this.CallEvent(DEMO.MSG.EVENT_TYPE.OnTest, "Send Active_test");
                }
                else
                {
                    //socket is closed!
                }
            }

            private void CallEvent(MSG.EVENT_TYPE event_type, object objValue)
            {
                if (this.onDEMOEvent != null)
                {
                    MSG.DEMOEventArgs DEMOevent = new DEMO.MSG.DEMOEventArgs();
                    DEMOevent.Event_Type = event_type;
                    switch (event_type)
                    {
                        case MSG.EVENT_TYPE.OnClientMsg:
                            DEMOevent.clientMsg = (MSG.ClientMsg)objValue;
                            break;
                        case MSG.EVENT_TYPE.OnServerMsg:
                            DEMOevent.serverMsg = (MSG.ServerMsg)objValue;
                            break;
                        default:
                            DEMOevent.Msg = (string)objValue;
                            break;
                    }
                    DEMOevent.SocketIndex = this.Index;
                    this.onDEMOEvent(this, DEMOevent);
                }
            }


            #region define events
            public delegate void DEMOEventHandler(object sender, MSG.DEMOEventArgs e);
            public event DEMOEventHandler onDEMOEvent;
            #endregion

            bool Connected = false; //check socket is connected flag
            public bool IsLogin = false;

            System.Threading.Timer timer;
            public string IP;
            public int Port = 5016;
            public void Start()
            {
                timer = new System.Threading.Timer(new TimerCallback(TimeCall), null, 0, 15 * 1000);
                this.ConnectServer();

            }
            public void StartServer()
            {
                this.Connected = true;
                Thread recThread = new Thread(new ThreadStart(this.Receive));
                recThread.Start();
            }
            public void End()
            {
                this.Send_COMMAND(MSG.COMMAND_ID.TERMINATE);
                this.SocketClose("END");
            }

            private void SocketClose(string Msg)
            {
                log.Msg("SocketClose", "Socket Index=" + this.Index.ToString() + "," + Msg);
                this.IsLogin = false;
                this.Connected = false;
                this.socket.Shutdown(SocketShutdown.Both);
                this.socket.Close();

                if (!Msg.Equals("END"))
                {
                    Thread.Sleep(2000);
                    this.ConnectServer();
                }
            }
            private void ConnectServer()
            {
                this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    this.socket.Connect(IPAddress.Parse(IP), Port);

                }
                catch (Exception err)
                {
                    log.Msg("ERR_ConnectServer", "DEMO Index=" + this.Index.ToString() + " , Connect Server failure" + err.ToString());
                    this.SocketClose("ConnectServer");
                }
                if (this.socket.Connected)
                {

                    log.Msg("ConnectServer", this.Index.ToString() + "  , Connect Server");

                    this.Connected = true;
                    Thread recThread = new Thread(new ThreadStart(this.Receive));
                    recThread.Start();
                    this.Send_BIND();
                }
                else
                {
                    log.Msg("ERR_ConnectServer", this.Index.ToString() + "Connect Server failure");
                    this.SocketClose("ConnectServer");
                }

            }

            private void Receive()
            {

                int BodyLen = 0;
                int RecvLen = 0;

                while (this.Connected)
                {
                    try
                    {
                        #region Receive Msg

                        #region Header
                        MSG.MSG_HEADER header = new MSG.MSG_HEADER();
                        byte[] MsgHead = new byte[12];
                        if (this.socket.Available >= 12)
                        {
                            RecvLen = 0;
                            try
                            {
                                RecvLen = this.socket.Receive(MsgHead, 0, 12, SocketFlags.None);
                            }
                            catch (Exception err)
                            {
                                log.Msg("ERR_RecvMsgHead" + this.Index.ToString(), err.ToString());
                            }

                            if (RecvLen != 12)
                            {
                                log.Msg("ERR_RecvMsgHead_Len" + this.Index.ToString(), "recive bytes <> 12");

                            }
                            else
                            {
                                header = new MSG.MSG_HEADER(MsgHead);
                            }
                        }
                        else
                        {
                            Thread.Sleep(100);
                            continue;
                        }
                        #endregion
                        #region Recv MsgBody
                        byte[] Body;
                        if (header.MSG_Length > 12)
                        {
                            RecvLen = 0;
                            BodyLen = (int)header.MSG_Length - 12;
                            if (header.MSG_Length > 500) //检查不正常的消息包
                            {

                                log.Msg("ERR_MsgHead" + this.Index.ToString(), "CommandID=" + header.Command_ID.ToString());
                                log.Msg("ERR_MsgHead" + this.Index.ToString(), "MsgLen=" + header.MSG_Length.ToString());
                                log.Msg("ERR_MsgHead" + this.Index.ToString(), "Socket.Available=" + this.socket.Available.ToString());
                                log.Bytes("ERR_MsgHead" + this.Index.ToString(), MsgHead);
                                byte[] buf = new byte[this.socket.Available + 10];
                                try
                                {
                                    this.socket.Receive(buf, 0, this.socket.Available, SocketFlags.None);
                                    log.Bytes("ERR_MsgHead" + this.Index.ToString(), MsgHead);

                                }
                                catch (Exception err)
                                {
                                    log.Msg("Err_RecvData_Buf" + this.Index.ToString(), err.ToString());

                                }
                                continue;
                            }
                            else
                            {
                                Body = new byte[BodyLen];
                            }
                            try
                            {
                                while (this.socket.Available < BodyLen)
                                {
                                    Thread.Sleep(300);
                                }
                                if (this.socket.Available >= BodyLen)
                                {
                                    RecvLen = this.socket.Receive(Body, 0, BodyLen, SocketFlags.None);
                                }
                                else
                                {
                                    //error 
                                }
                            }
                            catch (Exception err)
                            {
                                log.Msg("Err_RecvBody" + this.Index.ToString(), err.ToString());
                            }
                            if (BodyLen != RecvLen) continue;
                        }
                        else
                        {
                            Body = new byte[2];
                        }

                        byte[] Msg = new byte[header.MSG_Length];   //生成此消息的大小
                        for (int i = 0; i < header.MSG_Length; i++)
                        {
                            if (i < 12)
                            {
                                Msg[i] = MsgHead[i];
                            }
                            else
                            {
                                Msg[i] = Body[i - 12];
                            }
                        }

                        #endregion
                        #region switch CommmandID
                        switch (header.Command_ID)
                        {
                            case (uint)MSG.COMMAND_ID.BIND:
                                #region BIND
                                MSG.BIND bind = new TuiXin.DEMO.MSG.BIND(Msg);
                                this.Send_BIND_RESP(bind.BindResult, header.Seq_ID);
                                #endregion
                                break;
                            case (uint)MSG.COMMAND_ID.BIND_RESP:
                                #region BIND_RESP
                                this.IsLogin = true;
                                MSG.BIND_RESP BindResp = new MSG.BIND_RESP(Msg);
                                this.CallEvent(MSG.EVENT_TYPE.OnBindResp, BindResp.Result.ToString());
                                #endregion
                                break;
                            case (uint)MSG.COMMAND_ID.ACTIVE_TEST:
                                #region ACTIVE_TEST
                                this.CallEvent(MSG.EVENT_TYPE.OnTest, "Recv Active_test");
                                this.Send_COMMAND_RESP(MSG.COMMAND_ID.ACTIVE_TEST, header.Seq_ID);
                                #endregion
                                break;
                            case (uint)MSG.COMMAND_ID.ACTIVE_TEST_RESP:
                                this.CallEvent(MSG.EVENT_TYPE.OnTestResp, "Recv Active_test_resp");
                                break;
                            case (uint)MSG.COMMAND_ID.TERMINATE:
                                #region MSG_TERMINATE
                                this.Send_COMMAND_RESP(MSG.COMMAND_ID.TERMINATE, header.Seq_ID);
                                this.SocketClose("Terminate");
                                #endregion
                                break;
                            case (uint)MSG.COMMAND_ID.TERMINATE_RESP:
                                #region MSG_TERMINATE_RESP
                                this.SocketClose("Terminate_Resp");
                                #endregion
                                break;
                            case (uint)MSG.COMMAND_ID.CLIENT_MSG:
                                MSG.CLIENT_MSG clientMsg = new TuiXin.DEMO.MSG.CLIENT_MSG(Msg);
                                this.Send_COMMAND_RESP(TuiXin.DEMO.MSG.COMMAND_ID.CLIENT_MSG_RESP, header.Seq_ID);
                                log.Msg("ClientMsg", clientMsg.clientMsg.Name + "," + clientMsg.clientMsg.Quantity.ToString());
                                this.CallEvent(MSG.EVENT_TYPE.OnClientMsg, clientMsg.clientMsg);

                                break;
                            case (uint)MSG.COMMAND_ID.CLIENT_MSG_RESP:

                                MSG.CLIENT_MSG_RESP clientResp = new TuiXin.DEMO.MSG.CLIENT_MSG_RESP(Msg);
                                this.CallEvent(MSG.EVENT_TYPE.OnServerMsgResp, "");
                                break;
                            case (uint)MSG.COMMAND_ID.SERVER_MSG:

                            case (uint)MSG.COMMAND_ID.SERVER_MSG_RESP:
                                break;
                        #endregion
                                break;
                        }
                        #endregion

                    }
                    catch (SocketException err)
                    {
                        log.Msg("ERR_Receive_SocketException", err.ToString());

                    }
                    catch (Exception err)
                    {
                        log.Msg("Err_Receive_Exception", err.ToString());
                    }

                }

            }



            #region Send Message
            public void SendMsg(MSG.ClientMsg clientmsg)
            {
                if (this.IsLogin)
                {
                    MSG.CLIENT_MSG msg = new MSG.CLIENT_MSG(this.getNextSequence());
                    msg.clientMsg = clientmsg;
                    this.SendBytes(msg.GetBytes());
                }
                else
                {

                    log.Msg("ERR_SendMsg", "Socket is closed!");
                }
            }

            private void Send_COMMAND_RESP(MSG.COMMAND_ID cmdID, uint seqid)
            {
                switch (cmdID)
                {
                    case MSG.COMMAND_ID.ACTIVE_TEST:
                        MSG.MSG_TEST_RESP active_test_resp = new MSG.MSG_TEST_RESP(seqid);
                        this.SendBytes(active_test_resp.GetBytes());
                        break;

                    case MSG.COMMAND_ID.TERMINATE:
                        MSG.MSG_TERMINATE_RESP terminate_resp = new MSG.MSG_TERMINATE_RESP(seqid);
                        this.SendBytes(terminate_resp.GetBytes());
                        break;
                    case MSG.COMMAND_ID.CLIENT_MSG:
                        MSG.CLIENT_MSG_RESP clientMsg_resp = new TuiXin.DEMO.MSG.CLIENT_MSG_RESP(seqid);
                        this.SendBytes(clientMsg_resp.GetBytes());
                        break;
                    case MSG.COMMAND_ID.SERVER_MSG:
                        MSG.SERVER_MSG_RESP serverMsg_Resp = new TuiXin.DEMO.MSG.SERVER_MSG_RESP(seqid);
                        this.SendBytes(serverMsg_Resp.GetBytes());
                        break;
                }

            }
            private void Send_COMMAND(MSG.COMMAND_ID cmdID)
            {
                switch (cmdID)
                {
                    case MSG.COMMAND_ID.TERMINATE:
                        MSG.MSG_TERMINATE terminate = new MSG.MSG_TERMINATE(this.getNextSequence());
                        this.SendBytes(terminate.GetBytes());
                        break;
                    case MSG.COMMAND_ID.ACTIVE_TEST:
                        MSG.MSG_TEST active_test = new MSG.MSG_TEST(this.getNextSequence());
                        this.SendBytes(active_test.GetBytes());
                        break;
                }

            }

            private void Send_BIND_RESP(int result, uint seqid)
            {
                MSG.BIND_RESP Bindresp = new TuiXin.DEMO.MSG.BIND_RESP(seqid);
                Bindresp.Result = result;
                this.SendBytes(Bindresp.GetBytes());
            }
            private void Send_BIND()
            {
                MSG.BIND bind = new MSG.BIND(this.getNextSequence());

                bind.UserName = "DEMO";
                bind.Password = "DEMO";
                this.SendBytes(bind.GetBytes());
                log.Msg("SendBind", "bind");
            }
            private void SendBytes(byte[] sendbytes)
            {
                this.SendBytes(sendbytes, 3);

            }

            private void SendBytes(byte[] sendbytes, int MaxTimes)
            {
                int sent = 0;
                if (MaxTimes > 0)
                {
                    if (this.Connected)
                    {
                        lock (this.socket)
                        {
                            try
                            {
                                sent = this.socket.Send(sendbytes);
                                //log.Bytes("SendBytes", sendbytes);
                            }
                            catch (Exception err)
                            {
                                this.SocketClose("SendBytes");
                                log.Msg("Err_SendBytes", err.ToString());
                            }
                        }

                        if (sent != sendbytes.Length)
                        {
                            //error when socket send bytes , and then call self , resend bytes

                            SendBytes(sendbytes, MaxTimes - 1);
                        }
                    }
                    else
                    {
                        //socket is closed 
                        log.Msg("Err_sendBytes", "socket is closed!");
                    }
                }
                else
                {
                    //finished, send ok !
                }
            }

            #endregion
        }
    }


}
